
struct GameSpriteModel
{
    DecisionTree spriteAtTree;
    bool forceStasis;
};

struct GameVariableTree
{
    DecisionTree tree;
    bool absolute;
    int value;
};

inline OutputDataStream& operator << (OutputDataStream &stream, const GameVariableTree &variableTree)
{
    stream << variableTree.tree;
    stream << variableTree.absolute;
    stream << variableTree.value;
    return stream;
}

inline InputDataStream& operator >> (InputDataStream &stream, GameVariableTree &variableTree)
{
    stream >> variableTree.tree;
    stream >> variableTree.absolute;
    stream >> variableTree.value;
    return stream;
}

struct GameVariableModel
{
    vector<GameVariableTree> trees;
};

class GameModel
{
public:
    GameModel()
    {
        features = NULL;
    }

    ~GameModel()
    {
        if(features) delete[] features;
    }

    void Save(const string &filename) const;
    void Load(Game &game, const string &filename);

    void AdvanceFrame(const vector<const Frame*> &history, Frame &nextFrame) const;

    // Predict numSteps frames into the future

    inline const GameModelParameters& Parameters() const
    {
        return _parameters;
    }

private:
    friend class ModelLearner;

    Game* _game;
    GameModelParameters _parameters;

    vector<GameSpriteModel*> _spriteModels;
    vector<GameVariableModel*> _variableModels;

    short *features;
};
